package com.ld.common.util.filelistener.commonio;

import java.io.File;
import java.io.FileFilter;

import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;

import com.ld.shieldsb.common.core.io.FileUtils;
import com.ld.shieldsb.common.core.util.StringUtils;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * 文件监控model
 * 
 * @ClassName FileChangedListenerModel
 * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
 * @date 2019年1月18日 上午8:17:39
 *
 */
@Data
@Slf4j
public class FileChangedListenerModel {
    /** 名称 */
    private String name;
    /** 唯一识别码，用于注册到管理器时做识别 */
    private String keyCode;
    /** 监听文件路径 */
    private String path;
    /** 监控周期 */
    private long interval = 10000; // 默认10秒
    /** 允许的后缀，空表示不限制 */
    private String allowedExtensions;
    /** 排除的文件(正则) */
    private String exclusionRex;
    /** 监听器 */
    private FileAlterationListenerAdaptor listener;
    private FileFilter fileFilter; // 文件过滤器
    // ==========================以下无需赋值===================
    /** 是否已启动 */
    private boolean started = false;
    private FileAlterationMonitor fileMonitor = null;

    public FileChangedListenerModel() {
        super();
    }

    // 过滤器示例
//    static final class FileFilterImpl implements FileFilter {
//
//        /**
//         * @return return true:返回所有目录下所有文件详细(包含所有子目录)
//         * @return return false:返回主目录下所有文件详细(不包含所有子目录)
//         */
//        @Override
//        public boolean accept(File file) {
//            log.info("文件路径: " + file);
//            log.info("最后修改时间： " + file.lastModified());
//            return true;
//        }
//    }

    public FileChangedListenerModel(String name, String keyCode, String path, FileAlterationListenerAdaptor listener) {
        this(name, keyCode, path, null, listener);
    }

    public FileChangedListenerModel(String name, String keyCode, String path, Integer interval, FileAlterationListenerAdaptor listener) {
        this(name, keyCode, path, interval, null, null, listener);
    }

    public FileChangedListenerModel(String name, String keyCode, String path, Integer interval, String allowedExtensions,
            String exclusionRex, FileAlterationListenerAdaptor listener) {
        super();
        this.name = name;
        this.keyCode = keyCode;
        this.path = path;
        if (interval != null) {
            this.interval = interval;
        }
        this.allowedExtensions = allowedExtensions;
        this.exclusionRex = exclusionRex;
        this.listener = listener;
    }

    public void start() throws Exception {
        File file = new File(path);
        if (!file.exists()) {
            log.warn("文件监控器 " + name + " 启动失败，路径（" + path + "）不存在！");
            return;
        }
        if (isStarted()) {
            log.warn("文件监控器 " + name + " 已经启动，无需重复启动！");
        } else {
            // 构造观察类主要提供要观察的文件或目录，当然还有详细信息的filter
            if (StringUtils.isNotBlank(allowedExtensions) || StringUtils.isNotBlank(exclusionRex)) { //
                fileFilter = new FileFilter() {

                    @Override
                    public boolean accept(File pathname) {
                        if (StringUtils.isNotBlank(allowedExtensions)) { // 后缀
                            String extension = FileUtils.getFileExtension(pathname.getName());
                            if (extension != null && !allowedExtensions.contains(extension)) {
//                                log.debug("排除1：" + pathname.getName());
                                return false;
                            }

                        }
                        if (StringUtils.isNotBlank(exclusionRex)) { // 排除
                            String filePath = pathname.getAbsolutePath();
                            if (filePath.matches(exclusionRex)) {
//                                log.debug("排除2：" + filePath);
                                return false;
                            }

                        }
                        return true;
                    }
                };
            }
            FileAlterationObserver observer = new FileAlterationObserver(path, fileFilter);
            // 为观察对象添加收听对象
            observer.addListener(listener);
            // 配置Monitor，第一个参数单位是毫秒，是监听的间隔；第二个参数就是绑定我们之前的观察对象。
            fileMonitor = new FileAlterationMonitor(interval, new FileAlterationObserver[] { observer });
            // 启动开始监听
            fileMonitor.start();
            setStarted(true);
            log.warn("文件监控器 " + name + " 启动！");
        }
    }

    public void stop() throws Exception {
        // 关闭
        if (isStarted()) {
            fileMonitor.stop();
            setStarted(false);
            log.warn("文件监控器 " + name + " 关闭！");
        } else if (isStarted()) {
            log.warn("文件监控器 " + name + " 尚未启动，不能执行关闭操作！");
        }
    }

}
